home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / telecomm / uwsrc.arc / WINSUBR.C < prev   
Encoding:
C/C++ Source or Header  |  1989-04-29  |  28.3 KB  |  1,259 lines

  1. /* subroutines for multi-window terminal emulation
  2.  */
  3.  
  4. #include <obdefs.h>
  5. #include <gemdefs.h>
  6. #include <osbind.h>
  7. #include <stdio.h>
  8. #include "wind.h"
  9. #include "windefs.h"
  10.  
  11. extern int handle;
  12.  
  13. /* variables used by various routines
  14.  */
  15.  
  16. long dummy;                /* dummy return variable */
  17. extern    int    outwind, outport;    /* window selection */
  18. extern    int    scr_x, scr_y;        /* size of the screen */
  19. extern    int    scr_w, scr_h;
  20. extern    int    fast;            /* flag for fast open/close */
  21. extern    int    overstrike;
  22. extern    int    sliders;        /* flag for sliders on new windows */
  23. extern    int    titles;            /* flag for title bars on new windows */
  24. int    tmp;                /* temporary for anything... */
  25. extern    char    alert[300];        /* used for alerts */
  26. extern    FNT    *curfont;        /* current font */
  27. extern    MFDB    screen_mf;        /* screen descriptor */
  28. extern    int    mouse;            /* for mouse on/off */
  29. extern    int    audibell;        /* What happens on BEL? */
  30. extern    int    visibell;
  31. extern    int    toponbel;
  32.  
  33. struct    wi_str    w[MAX_WIND];
  34.  
  35. /* the program code...
  36.  */
  37.  
  38. char *getmem(size)
  39. register long size;
  40. {
  41.   char *got;
  42.  
  43.   got = (char *) Malloc(size);
  44. #ifdef DEBUG
  45.   printf("alloc returned %lx of %ld size\n", got, size);
  46. #endif
  47.   if (got == NULL)
  48.   {
  49.     sprintf(alert, "[1][Could not get %ld bytes][Ok]", size);
  50.     form_alert(1, alert);
  51.   } else
  52.   {
  53.     bzero(got, size);
  54.   }
  55.   return got;
  56. }
  57.  
  58. bzero(ptr, size)
  59. register char *ptr;
  60. register long size;
  61. {
  62.   while (size--)
  63.     *ptr++ = 0;
  64. }
  65.  
  66. /* find_port maps from window handles to UW port identifiers
  67.  */
  68.  
  69. find_port(wnd)
  70. {
  71.   return w[wnd].port;
  72. }
  73.  
  74. /* find_wind maps from port ids to window handles
  75.  */
  76.  
  77. find_wind(port)
  78. {
  79. int i;
  80.  
  81.   for (i=1; i<MAX_WIND; i++)
  82.     if (w[i].port == port) return i;
  83.   return 0;
  84. }
  85.  
  86. /* w_open opens a window with the supplied name and port and returns a port
  87.  * number.  If port was zero, a free port is chosen.
  88.  */
  89.  
  90. w_open(port, name, xsiz, ysiz)
  91. char *name;
  92. {
  93.   register struct wi_str *wp;
  94.   int wdes;
  95.   int i, cnt, wtyp;
  96.   int tmp_x, tmp_y, tmp_w, tmp_h;
  97.  
  98.   if (port && find_wind(port)) return port;  /* this window is already open */
  99.   if (!port)
  100.   {
  101.     for (i=1; i<MAX_WIND; i++)
  102.     {
  103.       if (!find_wind(i))
  104.       {
  105.         port = i;        /* a free port */
  106.         break;
  107.       }
  108.     }
  109.   }
  110.  
  111.   wtyp = (sliders ? WI_WITHSLD : 0) | (titles ? WI_NOSLD : 0);
  112.   wind_calc(0, wtyp, 0, 0, curfont->inc_x*xsiz+2*X0,
  113.     curfont->inc_y*ysiz+2*Y0, &dummy, &dummy, &tmp_w, &tmp_h);
  114.   if (tmp_w>scr_w)
  115.     tmp_w = scr_w;    /* full size <= screen size */
  116.   tmp_x = 10*(port-1);
  117.   if (tmp_h>scr_h)
  118.     tmp_h = scr_h;
  119.   tmp_y = scr_y+16*(port-1);
  120.  
  121.   wdes = wind_create(wtyp, tmp_x, tmp_y, tmp_w,
  122.     tmp_h);
  123.   if (wdes < 0)
  124.   {
  125.     form_alert(1, "[1][Sorry, GEM has|no more windows|for us...][Ok]");
  126.     return 0;
  127.   }
  128.   wp = &w[wdes];
  129.   wp->wi_w = X0*2 + curfont->inc_x*xsiz;
  130.   wp->wi_h = Y0*2 + curfont->inc_y*ysiz;
  131.   wp->port = port;
  132.   if (!fast)
  133.     graf_growbox(0, 0, 20, 10, tmp_x, tmp_y, tmp_w, tmp_h);
  134.   wind_open(wdes, tmp_x, tmp_y, tmp_w, tmp_h);
  135.   wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
  136.   wp->fulled = 0;
  137.   wp->used = 1;
  138.   wp->x_off = 0;
  139.   wp->y_off = 0;
  140.   wp->px_off = 0;
  141.   wp->py_off = 0;
  142.   wp->m_off = wp->x & 15;
  143.   wp->cur_x = X0;
  144.   wp->cur_y = Y0;
  145.   wp->top_y = Y0;
  146.   wp->font = curfont;
  147.   wp->x_chrs = xsiz;
  148.   wp->y_chrs = ysiz;
  149.   wp->wi_mf.wpix = 2*X0 + xsiz*curfont->inc_x;
  150.   wp->wi_mf.hpix = 2*Y0 + ysiz*curfont->inc_y;
  151. #ifdef    KOPY
  152.   wp->wi_mf.wwords = ((wp->wi_mf.wpix>>5) +1) << 1;
  153. #else
  154.   wp->wi_mf.wwords = (wp->wi_mf.wpix>>4) +1;
  155. #endif
  156.   wp->wi_mf.ptr = getmem(((long)wp->wi_mf.hpix+wp->font->inc_y*MAXSCROLLED)
  157.                 *wp->wi_mf.wwords*2);
  158.   wp->wi_mf.format = 0;
  159.   wp->wi_mf.planes = 1;
  160.   wp->ptr_status = LOG_NONE;
  161.   wp->wi_style = wtyp;
  162.   w_rename(wdes, name);
  163.   strcpy(wp->wi_fpath, ".\\*.*");
  164.   wp->top_age = 1;
  165.   for (cnt = 1; cnt < MAX_WIND; cnt++)
  166.     if (w[cnt].port != 0)
  167.       w[cnt].top_age++;
  168.   
  169.   setvslide(wdes);
  170.   sethslide(wdes);
  171.   
  172.   return wp->port;
  173. }
  174.  
  175. /* w_closei removes a window but does not release its storage.
  176.  * This is used if the window contents must be saved for later use.
  177.  */
  178.  
  179. w_closei(wdes)
  180. {
  181.   int xx, yy, ww, hh;
  182.   register struct wi_str *wp = &w[wdes];
  183.  
  184.   if (!wp->used) return;
  185.   if (wp->wi_lfd)
  186.     fclose(wp->wi_lfd);
  187.   wind_get(wdes, WF_CURRXYWH, &xx, &yy, &ww, &hh);
  188.   wind_close(wdes);
  189.   if (!fast)
  190.     graf_shrinkbox(0, 0, 20, 10, xx, yy, ww, hh);
  191.   wind_delete(wdes);
  192. }
  193.  
  194. /* w_close removes a window.  Most work is done by GEM, although w_close
  195.  * does some cleanup functions, too.
  196.  */
  197.  
  198. w_close(wdes)
  199. {
  200.   register struct wi_str *wp = &w[wdes];
  201.  
  202.   if (!wp->used) return;
  203.   w_closei(wdes);
  204.   Mfree(wp->wi_mf.ptr);
  205.   bzero(wp, (long)sizeof (struct wi_str));
  206. }
  207.  
  208. /* w_resize resizes an existing window.
  209.  */
  210.  
  211. w_resize(wdes, xsiz, ysiz)
  212. {
  213.   register struct wi_str *wp1 = &w[wdes];
  214.   struct wi_str *wp2;
  215.   struct wi_str ws;
  216.   static int c[8];
  217.   int port, wind, i;
  218.  
  219.   if (!wp1->used) return;
  220.   ws = *wp1;
  221.   port = find_port(wdes);
  222.   w_closei(wdes);
  223.   bzero(wp1, (long)sizeof (struct wi_str));
  224.   port = w_open(port, "", xsiz, ysiz);
  225.   wind = find_wind(port);
  226.   wp2 = &w[wind];
  227.   c[0] = ws.m_off;
  228.   c[1] = ws.top_y + max(0, ws.wi_mf.hpix - wp2->wi_mf.hpix);
  229.   c[2] = c[0] + min(ws.wi_mf.wpix, wp2->wi_mf.wpix);
  230.   c[3] = c[1] + min(ws.wi_mf.hpix, wp2->wi_mf.hpix);
  231.   c[4] = wp2->m_off;
  232.   c[5] = wp2->top_y;
  233.   c[6] = c[4] + min(ws.wi_mf.wpix, wp2->wi_mf.wpix);
  234.   c[7] = c[5] + min(ws.wi_mf.hpix, wp2->wi_mf.hpix);
  235.   /* copy screen */
  236.   vro_cpyfm(handle, FM_COPY, c, &ws.wi_mf, &wp2->wi_mf);
  237.   /* copy parameters */
  238.   wp2->inverse = ws.inverse;
  239.   wp2->insmode = ws.insmode;
  240.   if (wp2->font != ws.font)
  241.   {
  242.     wp2->cur_x = X0;
  243.     wp2->cur_y = (wp2->y_chrs - 1) * wp2->font->inc_y + Y0;
  244.   }
  245.   else
  246.   {
  247.     wp2->cur_x = (wp2->x_chrs - 1) * wp2->font->inc_x + X0;
  248.     if (ws.cur_x < wp2->cur_x)
  249.       wp2->cur_x = ws.cur_x;
  250.     wp2->cur_y = max(0, ws.cur_y - c[1]) + Y0;
  251.   }
  252.   wp2->state = ws.state;
  253.   for (i=0; i<80; i++) wp2->nuname[i] = ws.nuname[i];
  254.   for (i=0; i<80; i++) wp2->wi_fpath[i] = ws.wi_fpath[i];
  255.   for (i=0; i<20; i++) wp2->wi_fname[i] = ws.wi_fname[i];
  256.   wp2->nuptr = ws.nuptr;
  257.   wp2->ptr_status = ws.ptr_status;
  258.   wp2->wi_lfd = ws.wi_lfd;
  259.   wp2->kerm_act = ws.kerm_act;
  260.   w_rename(wind, ws.name);
  261.   
  262.   Mfree(ws.wi_mf.ptr);
  263.   return port;
  264. }
  265.  
  266. /* w_rename changes the title bar of a window
  267.  */
  268.  
  269. w_rename(wdes, name)
  270. char *name;
  271. {
  272.   register struct wi_str *wp = &w[wdes];
  273.  
  274.   if (name)
  275.     strcpy(wp->name, name);
  276.   if (wp->wi_style & NAME)
  277.   {
  278.     sprintf(wp->dname, " %s%s %s ", (wp->ptr_status != LOG_NONE)? "\275": "",
  279.       wp->wi_lfd? "\237": "", wp->name);
  280.     wind_set(wdes, WF_NAME, wp->dname + (wp->dname[1] == ' '), 0, 0);
  281.   }
  282. }
  283.  
  284. /* w_redraw redraws part of the screen from window contents.
  285.  * The coordinates are screen relative.
  286.  */
  287.  
  288. w_redraw(wdes, logic, xx, yy, ww, hh)
  289. {
  290.   static int c[8];
  291.   static GRECT t1, t2;
  292.   register struct wi_str *wp = &w[wdes];
  293.  
  294.   if (xx+ww > scr_w)
  295.     ww = scr_w - xx;
  296.   if (yy+hh > scr_h+scr_y)
  297.     hh = scr_h+scr_y - yy;
  298.   t2.g_x = xx; t2.g_y = yy;
  299.   t2.g_w = ww; t2.g_h = hh;
  300.   t1.g_x = wp->x; t1.g_y = wp->y;
  301.   t1.g_w = wp->w; t1.g_h = wp->h;
  302.   if (!rc_intersect(&t2, &t1)) return;    /* nothing to do... */
  303.   wind_update(TRUE);
  304.   wind_get(wdes, WF_FIRSTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  305.   while (t1.g_w && t1.g_h)
  306.   {
  307.     if (rc_intersect(&t2, &t1))
  308.     {
  309.       if (mouse)
  310.       {
  311.     /* we have to do graphics, so switch the mouse off.
  312.      * mouse will be switched on again in main loop.
  313.      * this is ugly, but it improves speed a bit...
  314.      */
  315.     mouse = 0;
  316.     graf_mouse(M_OFF, NULL);
  317.       }
  318. #ifdef    KCOPY
  319.       tfbmr(wp->wi_mf.ptr, t1.g_x - wp->x + wp->x_off + wp->m_off,
  320.     t1.g_y - wp->y + wp->y_off + wp->top_y - Y0, wp->wi_mf.wwords >> 1,
  321.     screen_mf.ptr, t1.g_x, t1.g_y, screen_mf.wwords >> 1,
  322.     t1.g_w, t1.g_h, logic);
  323. #else
  324.       c[0] = t1.g_x - wp->x + wp->x_off + wp->m_off;
  325.       c[1] = t1.g_y - wp->y + wp->y_off + wp->top_y - Y0;
  326.       c[2] = c[0] + t1.g_w - 1;
  327.       c[3] = c[1] + t1.g_h - 1;
  328.       c[4] = t1.g_x;
  329.       c[5] = t1.g_y;
  330.       c[6] = c[4] + t1.g_w - 1;
  331.       c[7] = c[5] + t1.g_h - 1;
  332.       vro_cpyfm(handle, logic, c, &wp->wi_mf, &screen_mf);
  333. #endif
  334.     }
  335.     wind_get(wdes, WF_NEXTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  336.   }
  337.   if (!fast && !mouse)
  338.   {
  339.     mouse = 1;
  340.     graf_mouse(M_ON, NULL);
  341.   }
  342.   wind_update(FALSE);
  343. }
  344.  
  345. /* w_update copies a portion of the window to the screen.  Coordinates
  346.  * are window-relative
  347.  */
  348.  
  349. w_update(wdes, logic, xx, yy, ww, hh)
  350. {
  351.   register struct wi_str *wp = &w[wdes];
  352.  
  353.   w_redraw(wdes, logic, xx + wp->x - wp->x_off, 
  354.           yy + wp->y - wp->y_off - wp->top_y + Y0, ww, hh);
  355. }
  356.  
  357. /* w_move sets the window's idea of its own position on the screen
  358.  */
  359.  
  360. w_move(wdes, xx, yy, ww, hh)
  361. {
  362.   register struct wi_str *wp = &w[wdes];
  363.   int flag = 0;
  364.   int m_w, m_h;
  365.   int x1, x2;
  366.   int tmp;
  367.  
  368.   wind_calc(1, wp->wi_style, xx, yy, ww, hh, &dummy, &dummy, &m_w, &m_h);
  369.   if (tmp = (m_w-2*X0)%wp->font->inc_x)
  370.   {
  371.     ww -= tmp;
  372.     m_w -= tmp;
  373.   }
  374.   if (tmp = (m_h-2*Y0)%wp->font->inc_y)
  375.   {
  376.     hh -= tmp;
  377.     m_h -= tmp;
  378.   }
  379.   if (m_w>wp->wi_w) ww = ww-(m_w-wp->wi_w);
  380.   if (m_h>wp->wi_h) hh = hh-(m_h-wp->wi_h);
  381.   wind_set(wdes, WF_CURRXYWH, xx, yy, ww, hh);
  382.   wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
  383.   if (wp->x_off+wp->w > wp->wi_w)
  384.   {
  385.     register int inc_x = wp->font->inc_x;
  386.     flag = 1;
  387.     wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
  388.   }
  389.   if (wp->y_off+wp->h > wp->wi_h)
  390.   {
  391.     register int inc_y = wp->font->inc_y;
  392.     flag = 1;
  393.     wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
  394.   }
  395.   x1 = wp->m_off;
  396.   x2 = (wp->x - wp->x_off) & 15;
  397.   if (x1 != x2)
  398.   {
  399. #ifdef    KOPY
  400.     int top = wp->top_y;
  401.     int cnt = wp->wi_mf.wwords >> 1;
  402.     cpbmr(wp->wi_mf.ptr, x1, top, cnt, wp->wi_mf.ptr, x2, top, cnt,
  403.       wp->wi_w, wp->wi_h);
  404. #else
  405.   int c[8];
  406.     c[0] = x1;
  407.     c[1] = wp->top_y;    /* displayed part of memory form starts here */
  408.     c[2] = x1 + wp->wi_w - 1;
  409.     c[3] = wp->wi_h - 1 + c[1];
  410.     c[4] = x2;
  411.     c[5] = c[1];
  412.     c[6] = x2 + wp->wi_w - 1;
  413.     c[7] = c[3];
  414.     vro_cpyfm(handle, 3, c, &wp->wi_mf, &wp->wi_mf);
  415. #endif
  416.     wp->m_off = x2;
  417.   }
  418.   if (flag)
  419.     w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  420.   setvslide(wdes);
  421.   sethslide(wdes);
  422. }
  423.  
  424. /*
  425.  * w_top makes win the top window.
  426.  */
  427. w_top(win)
  428. int win;
  429. {
  430.   int cnt;
  431.  
  432.   wind_set(win, WF_TOP, 0, 0, 0, 0);
  433.   outport = find_port(win);
  434.   outwind = win;
  435.   w[outwind].top_age = 0;
  436.   for (cnt = 1; cnt < MAX_WIND; cnt++)
  437.     if (find_port(cnt))    /* if window is in use */
  438.       w[cnt].top_age++;
  439.   printer_mark(outwind);
  440. }
  441.  
  442. /*
  443.  * w_bottom finds the bottom window and puts it on top
  444.  */
  445. w_bottom()
  446. {
  447.   int i;
  448.   int highwin, highcnt;
  449.   
  450.   highcnt = 0;
  451.   highwin = 1;
  452.   for (i = 1; i < MAX_WIND; i++)
  453.     if (w[i].top_age > highcnt)
  454.     {
  455.       highcnt = w[i].top_age;
  456.       highwin = i;
  457.     }
  458.   if (w[highwin].used)
  459.     w_top(highwin);
  460. }
  461.  
  462. /*
  463.  * w_hide puts the top window on the bottom.  The new top window is returned.
  464.  */
  465. int w_hide()
  466. {
  467.   int i, j;
  468.   int newtop, botwin, highcnt;
  469.   int oldtop, dum;
  470.   
  471.   wind_get(0, WF_TOP, &oldtop, &dum, &dum, &dum);
  472.   if (!oldtop)
  473.     return (0);
  474.   j = -1;
  475.   botwin = 0;
  476.   for (j = -1; ; j--)
  477.   {
  478.     newtop = botwin;
  479.     botwin = oldtop;
  480.     highcnt = 0;
  481.     for (i = 1; i < MAX_WIND; i++)
  482.     {
  483.       if (w[i].top_age > highcnt)
  484.       {
  485.         highcnt = w[i].top_age;
  486.         botwin = i;
  487.       }
  488.     }
  489.     if (botwin == oldtop)
  490.       break;
  491.     wind_set(botwin, WF_TOP, 0, 0, 0, 0);
  492.     w[botwin].top_age = j; /*top_age less than untouched windows (top_age < 0)*/
  493.   }
  494.   for (j = 1; j < MAX_WIND; j++)
  495.     if (find_port(j)) /* if window is in use */
  496.       w[j].top_age += MAX_WIND + 3; /* correct top_age to reflect new order */
  497.   return(newtop ? newtop : oldtop);
  498. }
  499.  
  500. #define TINYX 80
  501. #define TINYY 70
  502. /*
  503.  * w_shrink saves current size and location and shrinks to standard tiny size.
  504.  * The second from the top non-shrunk window is placed on top.
  505.  */
  506. w_shrink(wdes)
  507. int wdes;
  508. {
  509.   register struct wi_str *wp = &w[wdes];
  510.   int curw, dummy;
  511.   
  512.   /*
  513.    * Don't shrink a window that is currently shrunk
  514.    */
  515.   wind_get(wdes, WF_CURRXYWH, &dummy, &dummy, &curw, &dummy);
  516.   if (curw <= TINYX)
  517.     return;
  518.  
  519.   /*
  520.    * Set up fulled and previous size and location window variables to tiny
  521.    * size.  Then call w_full
  522.    */
  523.   wp->fulled = 1;
  524.   wp->px = scr_x + scr_w - TINYX + 2;
  525.   wp->py = scr_y + (wdes - 1) * (TINYY - 2);
  526.   wp->pw = TINYX;
  527.   wp->ph = TINYY;
  528.   if (wp->py + 10 > scr_y + scr_h)
  529.   {
  530.     wp->py = wp->py - scr_h + 10;
  531.     wp->px = scr_x + scr_w - TINYY * 2;
  532.   }
  533.   
  534.   return (w_full(wdes));
  535. }
  536.  
  537. /* w_full toggles size and location
  538.  */
  539. w_full(wdes)
  540. {
  541.   register struct wi_str *wp = &w[wdes];
  542.   int x1, y1, w1, h1;
  543.   int x2, y2, w2, h2;
  544.   int full, topwin;
  545.  
  546.   full = wp->fulled;
  547.   if (full) {
  548.     x1 = wp->px;
  549.     y1 = wp->py;
  550.     w1 = wp->pw;
  551.     h1 = wp->ph;
  552.   } else
  553.     wind_get(wdes, WF_FULLXYWH, &x1, &y1, &w1, &h1);
  554.  
  555.   wind_get(wdes, WF_CURRXYWH, &x2, &y2, &w2, &h2);
  556.   wp->px = x2;
  557.   wp->py = y2;
  558.   wp->pw = w2;
  559.   wp->ph = h2;
  560.   if (!fast)
  561.   {
  562.     if (w2>=w1 && h2>=h1)
  563.       graf_growbox(x2, y2, w2, h2, x1, y1, w1, h1);
  564.     else if (w2<=w1 && h2<=h1)
  565.       graf_shrinkbox(x1, y1, w1, h1, x2, y2, w2, h2);
  566.   }
  567.  
  568.   x2 = wp->x_off;
  569.   y2 = wp->y_off;
  570.   wp->x_off = wp->px_off;
  571.   wp->y_off = wp->py_off;
  572.   wp->px_off = x2;
  573.   wp->py_off = y2;
  574.  
  575.   w_move(wdes, x1, y1, w1, h1);
  576.   w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  577.   wp->fulled = 1;
  578.   topwin = wdes;
  579.   if (h1 < TINYY + 10)
  580.   {
  581.     int lowcnt, i;
  582.   
  583.     lowcnt = 32000;
  584.     for (i = 1; i< MAX_WIND; i++)
  585.     {
  586.       if (find_port(i))
  587.       {
  588.         wind_get(i, WF_CURRXYWH, &x2, &y2, &w2, &h2);
  589.       
  590.         if (w[i].top_age < lowcnt && h2 > TINYY + 10 )
  591.         { /* find top non-tiny open window */
  592.           lowcnt = w[i].top_age;
  593.           topwin = i;
  594.     }
  595.       }
  596.     }
  597.     wind_set(topwin, WF_TOP, 0, 0, 0, 0);
  598.   }
  599.   return(topwin);
  600. }
  601.  
  602. w_arrow(wdes, arrow)
  603. {
  604.   register struct wi_str *wp = &w[wdes];
  605.   int inc_x = wp->font->inc_x;
  606.   int inc_y = wp->font->inc_y;
  607.  
  608.   switch (arrow)
  609.   {
  610.   case 0:    /* page up */
  611.     wp->y_off -= wp->h/inc_y*inc_y;
  612.     goto y_upd;
  613.  
  614.   case 1:    /* page down */
  615.     wp->y_off += wp->h/inc_y*inc_y;
  616.     goto y_upd;
  617.  
  618.   case 2:    /* row up */
  619.     wp->y_off -= inc_y;
  620.     goto y_upd;
  621.  
  622.   case 3:    /* row down */
  623.     wp->y_off += inc_y;
  624.     goto y_upd;
  625.  
  626.   case 4:    /* page left */
  627.     wp->x_off -= wp->w/inc_x*inc_x;
  628.     goto x_upd;
  629.  
  630.   case 5:    /* page right */
  631.     wp->x_off += wp->w/inc_x*inc_x;
  632.     goto x_upd;
  633.  
  634.   case 6:    /* column left */
  635.     wp->x_off -= inc_x;
  636.     goto x_upd;
  637.  
  638.   case 7:    /* column right */
  639.     wp->x_off += inc_x;
  640.     goto x_upd;
  641.   }
  642.  
  643. x_upd:
  644.   if (wp->x_off<0) wp->x_off = 0; else
  645.   if (wp->x_off+wp->w > wp->wi_w) wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
  646.   sethslide(wdes);
  647.   goto upd;
  648.  
  649. y_upd:
  650.   if (wp->y_off<0) wp->y_off = 0; else
  651.   if (wp->y_off+wp->h > wp->wi_h) wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
  652.   setvslide(wdes);
  653.   
  654. upd:
  655.   w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  656. }
  657.  
  658. w_slide(wdes, hor, val)
  659. {
  660.   register struct wi_str *wp = &w[wdes];
  661.  
  662.   if (hor)
  663.   {
  664.     tmp = wp->font->inc_x;
  665.     wp->x_off = ((long)val*(wp->wi_w-wp->w)/1000)/tmp*tmp;
  666.     sethslide(wdes);
  667.   } else
  668.   {
  669.     tmp = wp->font->inc_y;
  670.     wp->y_off = ((long)val*(wp->wi_h-wp->h)/1000)/tmp*tmp;
  671.     setvslide(wdes);
  672.   }
  673.   w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  674. }
  675.  
  676. sethslide(wdes)
  677. {
  678.   register struct wi_str *wp = &w[wdes];
  679.  
  680.   if (wp->wi_style & HSLIDE)
  681.   {
  682.     tmp = (long)1000*wp->x_off/(wp->wi_w-wp->w);
  683.     wind_set(wdes, WF_HSLIDE, tmp, 0, 0, 0);
  684.     tmp = (long)1000*wp->w/wp->wi_w;
  685.     wind_set(wdes, WF_HSLSIZE, tmp, 0, 0, 0);
  686.   }
  687. }
  688.  
  689. setvslide(wdes)
  690. {
  691.   register struct wi_str *wp = &w[wdes];
  692.  
  693.   if (wp->wi_style & VSLIDE)
  694.   {
  695.     tmp = (long)1000*wp->y_off/(wp->wi_h-wp->h);
  696.     wind_set(wdes, WF_VSLIDE, tmp, 0, 0, 0);
  697.     tmp = (long)1000*wp->h/wp->wi_h;
  698.     wind_set(wdes, WF_VSLSIZE, tmp, 0, 0, 0);
  699.   }
  700. }
  701.  
  702. w_flash(wdes, state)
  703. {
  704.   register struct wi_str *wp = &w[wdes];
  705.   static int wdes_last;
  706. #ifdef    KOPY
  707.   int x, y, cnt;
  708. #else
  709.   int t[8];
  710. #endif
  711.  
  712.   if (wdes != wdes_last) w_flash(wdes_last, 1);
  713.   wdes_last = wdes;
  714.   if (!wp->used || wp->curstate == state) return;
  715.   if (state == 2)
  716.     wp->curstate = !wp->curstate;
  717.   else
  718.     wp->curstate = state;
  719. #ifdef    KOPY
  720.   x = wp->cur_x + wp->m_off;
  721.   y = wp->cur_y;
  722.   cnt = wp->wi_mf.wwords >> 1;
  723.   tfbmr(wp->wi_mf.ptr, x, y, cnt, wp->wi_mf.ptr, x, y, cnt,
  724.     wp->font->inc_x, wp->font->inc_y, 12);
  725. #else
  726.   t[0] = t[4] = wp->cur_x + wp->m_off;
  727.   t[1] = t[5] = wp->cur_y;
  728.   t[2] = t[6] = t[0]+wp->font->inc_x-1;
  729.   t[3] = t[7] = t[1]+wp->font->inc_y-1;
  730.   vro_cpyfm(handle, 12, t, &wp->wi_mf, &wp->wi_mf);
  731. #endif
  732.   w_update(wdes, FM_COPY, wp->cur_x, wp->cur_y, wp->font->inc_x, wp->font->inc_y);
  733. }
  734.   
  735. /* w_output prints a string onto the window.  The string may
  736.  * contain control chars and escape sequences.  It ends with \0.
  737.  */
  738.  
  739. w_output(wdes, ptr)
  740. char *ptr;
  741. {
  742.   register struct wi_str *wp = &w[wdes];
  743.   static char ch;
  744.   static int inc_x, cur_x;
  745.   static int state;
  746.   static int inc_y, cur_y;
  747. #ifdef    KOPY
  748.   int x, w, cnt;
  749. #else
  750.   static int t[8];
  751. #endif
  752.   static int f_x, f_y, f_mod;
  753.   static int scrolled;    /* Number of scrolling operations delayed */
  754.   static int xsiz, ysiz;/* Size in chars of terminal emulation for this window*/
  755.   register unsigned char *sptr;
  756.   register unsigned long *dptr;
  757.   register unsigned long mask;
  758.   register int shift;
  759.   register unsigned long val;
  760.   static int count;
  761.   static char * fdata;
  762.   static long width;
  763.   static char * wimfptr;
  764.   static int moffincx;
  765.   static char * savptr;
  766.   
  767.  
  768. #ifdef DEBUG
  769.   printf("entered w_output\n");
  770. #endif
  771.   if (!wp->font) return;
  772.   state = wp->state;
  773.   inc_x = wp->font->inc_x;
  774.   inc_y = wp->font->inc_y;
  775.   xsiz = wp->x_chrs;
  776.   ysiz = wp->y_chrs;
  777.   f_x = cur_x = wp->cur_x;
  778.   f_y = cur_y = wp->cur_y;
  779.   scrolled = wp->top_y/inc_y;
  780.   fdata = wp->font->f_data;
  781.   width = 2 * wp->wi_mf.wwords;
  782.   wimfptr = ((char *) (wp-> wi_mf.ptr)) - 2;
  783.   moffincx = wp->m_off + inc_x - 1;
  784.   f_mod = 0;
  785.   savptr = ptr;
  786.   
  787.   if (wp->curstate) w_flash(wdes, 0);
  788.  
  789.   while (ch = *ptr++)
  790.   {
  791.     switch (state)
  792.     {
  793.     case S_NORMAL:
  794.       if (ch >= ' ')
  795.       {
  796.     if (wp->insmode) /* open space for character */
  797.     {
  798. #ifdef    KOPY
  799.       x = cur_x + wp->m_off;
  800.       cnt = wp->wi_mf.wwords >> 1;
  801.       cpbmr(wp->wi_mf.ptr, x, cur_y, cnt,
  802.         wp->wi_mf.ptr, x + inc_x, cur_y, cnt,
  803.         (xsiz - 1) * inc_x + wp->m_off - x, inc_y);
  804. #else
  805.       t[0] = cur_x + wp->m_off;
  806.       t[1] = t[5] = cur_y;
  807.       t[2] = (xsiz - 1) * inc_x + wp->m_off - 1;
  808.       t[3] = t[7] = cur_y + inc_y - 1;
  809.       t[4] = t[0] + inc_x;
  810.       t[6] = t[2] + inc_x;
  811.       vro_cpyfm(handle, 3, t, &wp->wi_mf, &wp->wi_mf);
  812. #endif
  813.     }
  814.     /* paint the character */
  815.     sptr = fdata+ch*16;
  816.     dptr = wimfptr + cur_y*width
  817.         + (((moffincx + cur_x)>>4)<<1);
  818.     shift = 15 - ((moffincx + cur_x)&15);
  819.     if (overstrike)
  820.       mask = -1L;
  821.     else
  822.       mask = (-1L<<(shift+inc_x)|(1<<shift)-1);
  823.     if (wp->inverse)
  824.     {
  825.       for (count = inc_y; count; count--)
  826.       {
  827.         val = ((long)(*sptr++))<<shift ^ ~mask;
  828.         *dptr = (*dptr&mask)|val;
  829.         ((char *)dptr) += width;
  830.       }
  831.     } else
  832.     {
  833.       for (count = inc_y; count; count--)
  834.       {
  835.         val = ((long)(*sptr++))<<shift;
  836.         *dptr = (*dptr&mask)|val;
  837.         ((char *)dptr) += width;
  838.       }
  839.     }
  840.         cur_x += inc_x;
  841.     f_mod = 1;
  842.     if (cur_x > inc_x * xsiz) /* autowrap */
  843.     {
  844.       cur_y += inc_y;
  845.       if (cur_y >= wp->top_y + inc_y * ysiz) {
  846.         if (wp->ptr_status & LOG_TOP)
  847.           dump_line(wdes, 0);
  848.         wp->top_y += inc_y;
  849.         ++ scrolled;
  850.       }
  851.       if (! scrolled)
  852.       {
  853.         w_update(wdes, FM_COPY, f_x, f_y, cur_x-f_x, inc_y);
  854.         f_mod = 0;
  855.       }
  856.       cur_x = X0;
  857.  
  858.       f_x = cur_x;
  859.       f_y = cur_y;
  860.     }
  861.       } else /* not printable character */
  862.       {
  863.     if (f_mod && !scrolled)
  864.     {
  865.       if (!wp->insmode)
  866.         w_update(wdes, FM_COPY, f_x, f_y, cur_x - f_x, inc_y);
  867.       else
  868.         w_update(wdes, FM_COPY, f_x, f_y, xsiz * inc_x-f_x, inc_y);
  869.       f_mod = 0;
  870.     }
  871.     switch (ch)
  872.     {
  873.     case '\007':    /* Bell */
  874.       if (audibell)
  875.         Bconout(2, '\007');
  876.       if (toponbel)
  877.         /* put this window on top but don't make it the current window.
  878.          * should we set a flag so that the first input from the current
  879.          * window puts it back on top?
  880.          */
  881.         wind_set(wdes, WF_TOP, wdes, 0, 0, 0);
  882.       if (visibell)
  883.       {
  884.         w_redraw(wdes, FM_INVERT, wp->x, wp->y, wp->w, wp->h);
  885.         w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  886.         /* Should clear flag to prevent need for next update? */
  887.       }
  888.       break;
  889.  
  890.     case '\r':    /* Carriage Return */
  891.       cur_x = X0;
  892.       break;
  893.  
  894.     case '\b':    /* Backspace */
  895.       if (cur_x>X0) cur_x -= inc_x;
  896.       break;
  897.  
  898.     case '\n':    /* Newline */
  899.       cur_y += inc_y;
  900.       if (cur_y >= inc_y * ysiz + wp->top_y)
  901.       {
  902.         if (wp->ptr_status & LOG_TOP)
  903.           dump_line(wdes, 0);
  904.         wp->top_y += inc_y;
  905.         ++ scrolled;
  906.       }
  907.       break;
  908.  
  909.     case '\036':    /* Home */
  910.       cur_x = X0;
  911.       cur_y = wp->top_y;
  912.       break;
  913.  
  914.     case '\013':    /* Cursor Up */
  915.       if (cur_y!=wp->top_y) {
  916.         cur_y -= inc_y;
  917.       }
  918.       break;
  919.  
  920.     case '\014':    /* Cursor Right */
  921.       if (cur_x < (xsiz - 1) * inc_x) cur_x += inc_x;
  922.       break;
  923.  
  924.     case '\032':    /* Clear Screen */
  925.       wp->inverse = wp->insmode = 0;
  926.       cur_x = X0;
  927.       cur_y = Y0;
  928.       wp->top_y = Y0;
  929.       lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
  930.       ++ scrolled;
  931.       break;
  932.  
  933.     case '\t':    /* Tab */
  934.       cur_x = ((cur_x/inc_x/8+1))*inc_x*8+X0;
  935.       break;
  936.  
  937.     case '\033':    /* ESC */
  938.       state = S_ESC;
  939.       count = 0; /* count is used for insert or delete line */
  940.       break;
  941.     }
  942.     f_x = cur_x;
  943.     f_y = cur_y;
  944.       }
  945.       break;
  946.  
  947.     case S_ESC:
  948.       if (ch >= '0' && ch <= '9') {
  949.         count = count * 10 + ch - '0';
  950.     break;
  951.       }
  952.       switch (ch)
  953.       {
  954.       case '*':        /* Clear Screen */
  955.     f_x = cur_x = X0;
  956.     wp->top_y = f_y = cur_y = Y0;
  957.     wp->inverse = wp->insmode = 0;
  958.     lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
  959.     ++ scrolled;
  960.     state = S_NORMAL;
  961.     break;
  962.  
  963.       case 'Y':        /* Clear to End of Screen */
  964.     lineerase(wp, cur_y / inc_y + 1, ysiz - 1 + wp->top_y / inc_y);
  965.     if (! scrolled)
  966.       w_update(wdes, FM_COPY, X0, cur_y + inc_y, xsiz*inc_x, ysiz*inc_y);
  967.     /* fall through */
  968.       case 'T':        /* Clear to End of Line */
  969. #ifdef    KOPY
  970.     x = cur_x + wp->m_off;
  971.     cnt = wp->wi_mf.wwords >> 1;
  972.     tfbmr((short *) 0, 0, 0, 0, wp->wi_mf.ptr, x, cur_y, cnt,
  973.       X0 + xsiz * inc_x + wp->m_off - x, inc_y, 0);
  974. #else
  975.     t[0] = t[4] = cur_x + wp->m_off;
  976.     t[1] = t[5] = cur_y;
  977.     t[2] = t[6] = X0-1 + xsiz*inc_x +wp->m_off;
  978.     t[3] = t[7] = cur_y+inc_y-1;
  979.     vro_cpyfm(handle, 0, t, &wp->wi_mf, &wp->wi_mf);
  980. #endif
  981.     if (! scrolled)
  982.       w_update(wdes, FM_COPY, cur_x, cur_y, xsiz * inc_x - cur_x, inc_y);
  983.     state = S_NORMAL;
  984.     break;
  985.  
  986.       case 'E':        /* Add Line */
  987.       case 'R':        /* Delete Line */
  988.         if (count == 0) {
  989.       count = 1;
  990.       /* Look ahead for contiguous insert/delete line operations */
  991.       while (*ptr == '\033' && ptr[1] == ch) {
  992.         ptr +=2;
  993.         count ++;
  994.       }
  995.     }
  996.     if (ch == 'E')
  997.       scrolldn(wp, cur_y/inc_y, ysiz-(cur_y-wp->top_y+Y0)/inc_y-count, count);
  998.     else
  999.       scrollup(wp, cur_y / inc_y,
  1000.         ysiz - (cur_y - wp->top_y + Y0)/inc_y - count, count);
  1001.     if (! scrolled)
  1002.       w_update(wdes, FM_COPY, X0, cur_y, xsiz * inc_x,
  1003.         ysiz * inc_y - cur_y + wp->top_y - Y0);
  1004.     state = S_NORMAL;
  1005.     break;
  1006.  
  1007.       case 'q':        /* Insert Mode */
  1008.     wp->insmode = 1;
  1009.     state = S_NORMAL;
  1010.     break;
  1011.  
  1012.       case 'r':        /* End Insert */
  1013.     wp->insmode = 0;
  1014.     state = S_NORMAL;
  1015.     break;
  1016.  
  1017.       case 'W':        /* Delete Character */
  1018. #ifdef    KOPY
  1019.     x = cur_x + wp->m_off;
  1020.     w = X0 + xsiz * inc_x + wp->m_off - x;
  1021.     cnt = wp->wi_mf.wwords >> 1;
  1022.     cpbmr(wp->wi_mf.ptr, x + inc_x, cur_y, cnt,
  1023.       wp->wi_mf.ptr, x, cur_y, cnt, w, inc_y);
  1024.     tfbmr((short *) 0, 0, 0, 0,
  1025.       wp->wi_mf.ptr, X0 + (xsiz - 1) * inc_x + wp->m_off, cur_y, cnt,
  1026.       inc_x, inc_y, 0);
  1027. #else
  1028.     t[0] = cur_x + inc_x + wp->m_off;
  1029.     t[1] = t[5] = cur_y;
  1030.     t[2] = X0 - 1 + xsiz * inc_x + wp->m_off;
  1031.     t[3] = t[7] = cur_y+inc_y - 1;
  1032.     t[4] = t[0] - inc_x;
  1033.     t[6] = t[2] - inc_x;
  1034.     vro_cpyfm(handle, 3, t, &wp->wi_mf, &wp->wi_mf);
  1035.     t[0] = t[4] = X0 + (xsiz - 1) * inc_x + wp->m_off;
  1036.     t[2] = t[6] = t[0] + inc_x - 1;
  1037.     vro_cpyfm(handle, 0, t, &wp->wi_mf, &wp->wi_mf);
  1038. #endif
  1039.     if (! scrolled)
  1040.       w_update(wdes, FM_COPY, cur_x, cur_y, xsiz * inc_x - (cur_x - X0),
  1041.         inc_y);
  1042.     state = S_NORMAL;
  1043.     break;
  1044.  
  1045.       case '=':        /* Cursor Movement */
  1046.     state = S_ESC1;
  1047.     break;
  1048.  
  1049.       case 'G':        /* Switch Inverse/Normal */
  1050.     state = S_ESC2;
  1051.     break;
  1052.  
  1053.       case 'S':        /* Change Status Line */
  1054.     state = S_STATUS;
  1055.     wp->nuptr = 0;
  1056.     break;
  1057.     
  1058.       case '[':        /* ascii escape */
  1059.         state = S_ESCA;
  1060.     wp->nuptr = 0;
  1061.     break;
  1062.  
  1063.       default:        /* Unknown escape sequence */
  1064.     state = S_NORMAL;
  1065.       }
  1066.       break;
  1067.  
  1068.     case S_ESC1:    /* get line number */
  1069.       if (ch < ' ' || ch >= ' ' + ysiz) ch = ' ';
  1070.       f_y = cur_y = (ch-' ')*inc_y + wp->top_y;
  1071.       state = S_ESC3;
  1072.       break;
  1073.  
  1074.     case S_ESC3:    /* get column number */
  1075.       if (ch < ' ' || ch >= ' ' + xsiz) ch = ' ';
  1076.       f_x = cur_x = (ch-' ')*inc_x +X0;
  1077.       state = S_NORMAL;
  1078.       break;
  1079.  
  1080.     case S_ESC2:    /* get normal/inverse state */
  1081.       wp->inverse = ch&1;
  1082.       state = S_NORMAL;
  1083.       break;
  1084.  
  1085.     case S_STATUS:
  1086.       if (ch == '\r')
  1087.       {
  1088.     wp->nuname[wp->nuptr] = '\0';
  1089.     w_rename(wdes, wp->nuname);
  1090.     state = S_NORMAL;
  1091.       } else if (wp->nuptr < 72)
  1092.       {
  1093.     wp->nuname[wp->nuptr++] = ch;
  1094.       }
  1095.       break;
  1096.     case S_ESCA:
  1097.       if (ch >= '0' && ch <= '9')
  1098.         wp->nuptr = ch - '0' + 10 * wp->nuptr;
  1099.       else if (ch == 't')
  1100.       {
  1101.         if (wp-> nuptr == 18)
  1102.     {
  1103.       char posstr[20];
  1104.       
  1105.       sprintf(posstr, "\033[8;%d;%dt", ysiz, xsiz);
  1106.       proto_out(find_port(wdes), posstr, strlen(posstr));
  1107.     }
  1108.     state = S_NORMAL;
  1109.       }
  1110.       else state = S_NORMAL;
  1111.       break;
  1112.     } /* end switch on state */
  1113.  
  1114.     if (scrolled >= MAXSCROLLED)
  1115.     {
  1116.       if (wp->top_y != Y0) {
  1117.         scrollup(wp, 0, ysiz, wp->top_y/inc_y);
  1118.     wp->top_y = Y0;
  1119.         f_y = cur_y = Y0 + (ysiz - 1) * inc_y;
  1120.       }
  1121.       w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  1122.       scrolled = 0;
  1123.     }
  1124.   } /* end while loop for each character */
  1125.  
  1126.   if (wp->ptr_status & LOG_BOTOM) {
  1127.     ptr = savptr;
  1128.     while ((ch = *ptr++) && (wp->ptr_status & LOG_BOTOM))
  1129.       if (Cprnout(ch) == 0) wp->ptr_status = LOG_NONE;
  1130.   }
  1131.  
  1132.   if (wp->wi_lfd) {
  1133.     while (ch = *savptr++)
  1134.       putc(ch, wp->wi_lfd);
  1135.   }
  1136.  
  1137.   if (scrolled) {
  1138.     if (scrolled >= MAXSCROLLED) {
  1139.       if (wp->top_y != Y0) {
  1140.         scrollup(wp, 0, ysiz, wp->top_y/inc_y);
  1141.         wp->top_y = Y0;
  1142.         cur_y = Y0 + (ysiz - 1) * inc_y;
  1143.       }
  1144.     }
  1145.     w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  1146.   }
  1147.   else
  1148.     if (f_mod)
  1149.     {
  1150.       if (!wp->insmode)
  1151.         w_update(wdes, FM_COPY, f_x, f_y, cur_x - f_x, inc_y);
  1152.       else
  1153.         w_update(wdes, FM_COPY, f_x, f_y, xsiz * inc_x-f_x, inc_y);
  1154.     }
  1155.   wp->cur_x = cur_x;
  1156.   wp->cur_y = cur_y;
  1157.   wp->state = state;
  1158. #ifdef DEBUG
  1159.   printf ("calling w_flash\n");
  1160. #endif
  1161.   w_flash(wdes, 1);
  1162. }
  1163.  
  1164. lineerase(wp, first, last)
  1165. register struct wi_str *wp;
  1166. {
  1167.   register int *p;
  1168.   long count;
  1169.   long linespace = wp->wi_mf.wwords*wp->font->inc_y;
  1170.  
  1171.   p = wp->wi_mf.ptr + first*linespace + Y0*wp->wi_mf.wwords - 1;
  1172.   count = (last-first+1)*linespace;
  1173.   while (count > 7)
  1174.   {
  1175.     *(((long *)p)++) = 0;
  1176.     *(((long *)p)++) = 0;
  1177.     *(((long *)p)++) = 0;
  1178.     *(((long *)p)++) = 0;
  1179.     count -= 8;
  1180.   }
  1181.   while (--count >= 0)
  1182.     *++p = 0;
  1183. }
  1184.  
  1185. scrollup(wp, first, nlines, amount)
  1186. register struct wi_str *wp;
  1187. {
  1188.   register int *p1, *p2;
  1189.   register long count;
  1190.   int linespace = wp->wi_mf.wwords*wp->font->inc_y;
  1191.  
  1192.   p1 = wp->wi_mf.ptr + first*linespace + Y0*wp->wi_mf.wwords;
  1193.   p2 = p1 + linespace * amount;
  1194.   count = (long)(nlines)*linespace;
  1195.   while (count > 15)
  1196.   {
  1197.     *(((long *)p1)++) = *(((long *)p2)++);
  1198.     *(((long *)p1)++) = *(((long *)p2)++);
  1199.     *(((long *)p1)++) = *(((long *)p2)++);
  1200.     *(((long *)p1)++) = *(((long *)p2)++);
  1201.     *(((long *)p1)++) = *(((long *)p2)++);
  1202.     *(((long *)p1)++) = *(((long *)p2)++);
  1203.     *(((long *)p1)++) = *(((long *)p2)++);
  1204.     *(((long *)p1)++) = *(((long *)p2)++);
  1205.     count -= 16;
  1206.   }
  1207.   while (--count >= 0)
  1208.     *(p1++) = *(p2++);
  1209.   count = linespace * amount;
  1210.   while (count > 7)
  1211.   {
  1212.     *(((long *)p1)++) = 0;
  1213.     *(((long *)p1)++) = 0;
  1214.     *(((long *)p1)++) = 0;
  1215.     *(((long *)p1)++) = 0;
  1216.     count -= 8;
  1217.   }
  1218.   while (--count >= 0)
  1219.     *(p1++) = 0;
  1220. }
  1221.  
  1222. scrolldn(wp, first, nlines, amount)
  1223. register struct wi_str *wp;
  1224. {
  1225.   register int *p1, *p2;
  1226.   register long count;
  1227.   long linespace = wp->wi_mf.wwords*wp->font->inc_y;
  1228.  
  1229.   p1 = wp->wi_mf.ptr + (nlines+first+amount)*linespace + Y0*wp->wi_mf.wwords;
  1230.  
  1231.   p2 = p1 - linespace * amount;
  1232.   count = (long)(nlines)*linespace;
  1233.   while (count > 15)
  1234.   {
  1235.     *--(long *)p1 = *--(long *)p2;
  1236.     *--(long *)p1 = *--(long *)p2;
  1237.     *--(long *)p1 = *--(long *)p2;
  1238.     *--(long *)p1 = *--(long *)p2;
  1239.     *--(long *)p1 = *--(long *)p2;
  1240.     *--(long *)p1 = *--(long *)p2;
  1241.     *--(long *)p1 = *--(long *)p2;
  1242.     *--(long *)p1 = *--(long *)p2;
  1243.     count -= 16;
  1244.   }
  1245.   while (--count >= 0)
  1246.     *--p1 = *--p2;
  1247.   count = linespace * amount;
  1248.   while (count > 7)
  1249.   {
  1250.     *--(long *)p1 = 0L;
  1251.     *--(long *)p1 = 0L;
  1252.     *--(long *)p1 = 0L;
  1253.     *--(long *)p1 = 0L;
  1254.     count -= 8;
  1255.   }
  1256.   while (--count >= 0)
  1257.     *--p1 = 0;
  1258. }
  1259.